<?php
App::import('Vendor','Auth/OpenID/Association');
class CakeStore extends Auth_OpenID_OpenIDStore {
	var $Assoc = null;
	var $Nonce = null;
	var $virtualFields = array ('time_issued' => 'issued + lifetime' );
	function __construct(Assoc $assoc, Nonce $nonce) {
		if (is_object ( $assoc ) && is_object ( $nonce )) {
			$this->Assoc = $assoc;
			$this->Nonce = $nonce;
		}
	}
	function blobDecode($blob) {
		return $blob;
	}
	
	function blobEncode($str) {
		return $str;
	}
	/**
	 * Converts a query result to a boolean.  If the result is a
	 * database error according to $this->isError(), this returns
	 * false; otherwise, this returns true.
	 */
	function resultToBool($obj) {
		if ($this->isError ( $obj )) {
			return false;
		} else {
			return true;
		}
	}
	/**
	 * @return multitype:NULL 
	 */
	function cleanup() {
		return array ($this->cleanupNonces (), $this->cleanupAssociations () );
	}
	
	function cleanupNonces() {
		global $Auth_OpenID_SKEW;
		$v = time () - $Auth_OpenID_SKEW;
		$this->Nonce->deleteAll ( array ('timestamp <', $v ) );
		$num = $this->Nonce->getAffectedRows ();
		return $num;
	}
	
	function cleanupAssociations() {
		$this->Assoc->deleteAll ( array ('time_issued  <', time () ) );
		$num = $this->Assoc->getAffectedRows ();
		return $num;
	}
	
	function removeAssociation($server_url, $handle) {
		return $this->Assoc->deleteAll ( array ('server_url' => $server_url, 'handle' => $handle ) );
	}
	
	function getAssociation($server_url, $handle = null) {
		$assocs = array ();
		if ($handle !== null) {
			$assoc = $this->Assoc->find ( 'first', array ('conditions' => array ('server_url' => $server_url, 'handle' => $handle ) ) );
			if ($assoc) {
				$assocs [] = $assoc;
			}
		} else {
			$assocs = $this->Assoc->find ( 'all', array ('conditions' => array ('server_url' => $server_url ) ) );
		}
		
		if (! $assocs || (count ( $assocs ) == 0)) {
			return null;
		} else {
			$associations = array ();
			
			foreach ( $assocs as $assoc_row ) {
				$assoc = new Auth_OpenID_Association ( $assoc_row ['Association'] ['handle'], $assoc_row ['Association'] ['secret'], $assoc_row ['Association'] ['issued'], $assoc_row ['Association'] ['lifetime'], $assoc_row ['Association'] ['assoc_type'] );
				
				$assoc->secret = $this->blobDecode ( $assoc->secret );
				
				if ($assoc->getExpiresIn () == 0) {
					$this->removeAssociation ( $server_url, $assoc->handle );
				} else {
					$associations [] = array ($assoc->issued, $assoc );
				}
			}
			
			if ($associations) {
				$issued = array ();
				$assocs = array ();
				foreach ( $associations as $key => $assoc ) {
					$issued [$key] = $assoc [0];
					$assocs [$key] = $assoc [1];
				}
				
				array_multisort ( $issued, SORT_DESC, $assocs, SORT_DESC, $associations );
				
				// return the most recently issued one.
				list ( $issued, $assoc ) = $associations [0];
				return $assoc;
			} else {
				return null;
			}
		}
	}
	
	/**
	 * Resets the store by removing all records from the store's
	 * tables.
	 */
	function reset() {
		$this->Assoc->deleteAll ();
		$this->Nonce->deleteAll ();
	}
	
	function storeAssociation($server_url, $association) {
		
		if ($this->Assoc->find ( 'first', array ('conditions' => array ('server_url' => $server_url, 'handle' => $association->handle ) ) )) {
			$data ['id'] = $this->Assoc->id;
			//$data['secret'] = $this->blobEncode($association->secret);
			$data ['secret'] = $this->blobEncode ( '!' );
			$data ['issued'] = $association->issued;
			$data ['lifetime'] = $association->lifetime;
			$data ['assoc_type'] = $association->assoc_type;
			return $this->Assoc->save ( $data );
		} else {
			//$data['secret'] = $this->blobEncode($association->secret);
			$data ['secret'] = $this->blobEncode ( '!' );
			$data ['issued'] = $association->issued;
			$data ['lifetime'] = $association->lifetime;
			$data ['assoc_type'] = $association->assoc_type;
			$data ['server_url'] = $server_url;
			$data ['handle'] = $association->handle;
			return $this->Assoc->save ( $data );
		}
	}
	/**
	 * @return string
	 */
	public function supportsCleanup() {
	
	}
	
	function useNonce($server_url, $timestamp, $salt) {
		global $Auth_OpenID_SKEW;
		
		if (abs ( $timestamp - time () ) > $Auth_OpenID_SKEW) {
			return false;
		}
		return $this->Nonce->save ( array ('server_url' => $server_url, 'timestamp' => $timestamp, 'salt' => $salt ) );
	}

}